package net.stogi.dsper.ui.client.module.tag;

import java.util.ArrayList;
import java.util.List;

import net.stogi.common.gwt.dispatch.client.core.ActionManager;
import net.stogi.common.gwt.frame.client.core.EventBus;
import net.stogi.common.gwt.frame.client.mvp.AbstractPresenter;
import net.stogi.common.mvp.core.behavior.Behavior;
import net.stogi.common.mvp.core.behavior.BehaviorWithValue;
import net.stogi.common.mvp.core.model.KeyValues;
import net.stogi.dsper.api.dto.TagDto;
import net.stogi.dsper.ui.shared.module.tag.ListTagsAction;
import net.stogi.dsper.ui.shared.module.tag.ListTagsResult;

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.rpc.AsyncCallback;

class TagSelectorPresenter extends AbstractPresenter {

	private TagSelectorView tagSelectorView;

	private List<TagDto> tagListModel;

	public TagSelectorPresenter(TagSelectorView tagSelectorView, ActionManager actionManager, EventBus eventBus) {
		super(actionManager, eventBus);
		this.tagSelectorView = tagSelectorView;
		initBehavior();
		initHandlers();
	}

	@Override
	protected void initBehavior() {
		tagSelectorView.setSelectBehavior(new BehaviorWithValue<List<KeyValues<Long>>>() {

			@Override
			public void behave(List<KeyValues<Long>> values) {
				List<TagDto> selectedTagList = new ArrayList<TagDto>();
				for (KeyValues<Long> value : values) {
					TagDto selectedTag = internalGetTagFromModel(value.getKey());
					if (selectedTag != null) {
						selectedTagList.add(selectedTag);
					}
				}

				GWT.log("TagSelectorPresenter.behavior.select: [selectedTagList.size = '" + selectedTagList.size() + "']", null);

				tagSelectorView.disappear();
				eventBus.fireEvent(new TagsSelectedEvent(selectedTagList));
			}
		});
		tagSelectorView.setCancelBehavior(new Behavior() {

			@Override
			public void behave() {
				tagSelectorView.disappear();
				eventBus.fireEvent(new TagSelectorClosedEvent());
			}
		});
	}

	@Override
	protected void initHandlers() {
		eventBus.addHandler(OpenTagSelectorEvent.TYPE, new OpenTagSelectorHandler() {

			@Override
			public void onOpenTagSelector(OpenTagSelectorEvent event) {
				tagSelectorView.appear();
				executeListTags();
			}
		});
	}

	private void executeListTags() {
		actionManager.execute(new ListTagsAction(), new AsyncCallback<ListTagsResult>() {

			@Override
			public void onFailure(Throwable caught) {
				internalHandleException(caught);
			}

			@Override
			public void onSuccess(ListTagsResult result) {
				tagListModel = result.getTagList();
				internalDisplayTags(tagListModel);
			}
		});
	}

	private void internalDisplayTags(List<TagDto> tagList) {
		List<KeyValues<Long>> modelList = new ArrayList<KeyValues<Long>>();
		for (TagDto tag : tagList) {
			KeyValues<Long> model = new KeyValues<Long>(tag.getId());
			model.setValue("value", tag.getValue());
			modelList.add(model);
		}
		tagSelectorView.displayTags(modelList);
	}

	private void internalHandleException(Throwable caught) {
		// TODO: Add some nice message module in order to show messages from
		// exceptions to user.
		GWT.log("execute*: fail", null);
	}

	private TagDto internalGetTagFromModel(Long id) {
		assert id != null : "Parameter 'id' can not be null";
		for (TagDto tag : tagListModel) {
			if (id.equals(tag.getId())) {
				return tag;
			}
		}
		return null;
	}
}
